# -*- coding:utf-8 -*-

import os, sys, argparse
from pydantic_settings import BaseSettings
from functools import lru_cache
from dotenv import load_dotenv

class AppConfig(BaseSettings):
    """
    应用配置
    """

    app_env: str = 'dev'
    app_name: str = 'FastServer'
    app_root_path: str = '/dev-api'
    app_host: str = '0.0.0.0'
    app_port: int = 8000
    app_version: str = '0.0.1'
    app_reload: bool = True
    app_ip_location_query: bool = True
    app_same_time_login: bool = True
    api_prefix: str = '/fastapi'

class OpenApi(BaseSettings):
    """
    OpenAPI配置
    """
    openapi_url: str = '/fastapi/openapi.json'
    openapi_ui_url: str = '/fastapi/docs'
    openapi_ui_redoc_url: str = '/fastapi/redoc'

class Database(BaseSettings):
    """
    Database配置
    """
    db_host: str = '127.0.0.1'
    db_port: int = 3306
    db_username: str = 'root'
    db_password: str = 'root'
    db_database: str = 'fastapi_demo'
    db_charset: str = 'utf8mb4'
    db_collation: str = 'utf8mb4_general_ci'
    db_echo: bool = False
    db_type: str = 'sqlite'
    db_max_overflow: int = 100
    db_pool_size: int = 10
    db_pool_recycle: int = 3600
    db_pool_timeout: int = 30

class RedisConfig(BaseSettings):
    """
    Redis配置
    """
    redis_enable: bool = False
    redis_host: str = '127.0.0.1'
    redis_port: int = 6379
    redis_password: str = ''
    redis_db: int = 0
    redis_decode_responses: bool = True
    redis_encoding: str = 'utf-8'

class EmailConfig(BaseSettings):
    """
    Email配置
    """
    email_server: str = 'smtp.qq.com' # 邮箱服务器
    email_port: int = 465 # 邮箱端口, 587/465(SSL)
    email_username: str = 'xxx@qq.com' # 邮箱账号
    email_password: str = 'xxx' # 邮箱密码, 注意不是邮箱登录密码，而是授权码
    email_from: str = 'xxx@qq.com' # 发送者邮箱, 注意不是邮箱账号
    email_ssl_tls: bool = True # 是否使用SSL: 465
    email_starttls: bool = False # 是否使用TLS: 587
    email_use_credential: bool = True # 是否使用认证
    email_validate_cert: bool = False # 是否验证证书

class JwtConfig(BaseSettings):
    """
    Jwt配置
    """
    jwt_secret_key: str = '09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7'
    jwt_access_token_expires: int = 3600
    jwt_refresh_token_expires: int = 3600 * 24 * 7
    jwt_algorithm: str = 'HS256'
    jwt_oauth2_login_url: str = '/fastapi/api/v1/admin/auth/login'

class InitConfig(BaseSettings):
    """
    Init配置
    """
    verify_secret_key: str = '09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7'
    verify_code_expires: int = 3600

class MinioConfig(BaseSettings):
    """
    Minio配置
    """
    minio_endpoint: str = 'minio:9000'
    minio_access_key: str = 'minio'
    minio_secret_key: str = 'minio123'
    minio_secure: bool = False
    minio_bucket_name: str = 'fastapi-demo'
    minio_base_url: str = 'minio:9000'
    

class Config:
    """
    配置
    """

    def __init__(self):
        self.parse_cli_args()

    @lru_cache()
    def get_openapi_config(self):
        return OpenApi()

    @lru_cache()
    def get_app_config(self):
        return AppConfig()
    
    @lru_cache()
    def get_database_config(self):
        return Database()
    
    @lru_cache()
    def get_redis_config(self):
        return RedisConfig()
    
    @lru_cache()
    def get_email_config(self):
        return EmailConfig()

    @lru_cache()
    def get_jwt_config(self):
        return JwtConfig()

    @lru_cache()
    def get_init_config(self):
        return InitConfig()

    @lru_cache()
    def get_minio_config(self):
        return MinioConfig()

    @staticmethod
    def parse_cli_args():
        """
        解析命令行参数
        """
        if 'uvicorn' in sys.argv[0]:
            # 使用uvicorn启动时，命令行参数需要按照uvicorn的文档进行配置，无法自定义参数
            pass
        elif 'fastapi' in sys.argv[0]:
            # 使用uvicorn启动时，命令行参数需要按照uvicorn的文档进行配置，无法自定义参数
            pass
        else:
            # 使用argparse定义命令行参数
            parser = argparse.ArgumentParser(description='命令行参数')
            parser.add_argument('--env', type=str, default='', help='运行环境')
            # 解析命令行参数
            args = parser.parse_args()
            # 设置环境变量，如果未设置命令行参数，默认APP_ENV为dev
            os.environ['APP_ENV'] = args.env if args.env else 'dev'
        # 读取运行环境
        run_env = os.environ.get('APP_ENV', '')
        # 运行环境未指定时默认加载.env.dev
        env_file = '.env.dev'
        # 运行环境不为空时按命令行参数加载对应.env文件
        if run_env != '':
            env_file = f'.env.{run_env}'
        # 加载配置
        load_dotenv(env_file)
        print(f'加载配置文件: {env_file}')
        print('-' * 25)
        
config = Config()
AppConfig = config.get_app_config()
OpenApi = config.get_openapi_config()
DataBaseConfig = config.get_database_config()
RedisConfig = config.get_redis_config()
JwtConfig = config.get_jwt_config()
EmailConfig = config.get_email_config()
InitConfig = config.get_init_config()
MinioConfig = config.get_minio_config()